package cc.gpai.util.slotboard;

import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;


@SuppressWarnings("rawtypes")
public class CustomFactory {

	private Map<Class,Object> map = new HashMap<Class,Object>();
	public CustomFactory() {
		super();
	}
	public Object put(Class clazz, Object instance) {
		if((instance==null)||(clazz==null)){
			throw new NullPointerException();
		}
		if(!clazz.isInterface()){
			throw new IllegalArgumentException(""+clazz +" is not an interface.");
		}
		if(!clazz.isInstance(instance)){
			throw new ClassCastException(""+instance +" is not instance of "+clazz);
		}
		return map.put(clazz, instance);
	}
	
	public void putAll(Map<Class,Object> m) {
		for(Entry<Class, Object> e:m.entrySet()){
			put(e.getKey(),e.getValue());
		}
	}
	public Object remove(Class clazz) {
		return map.remove(clazz);
	}

	public <E> CustomSignal<E> createSignal(){
		return new CustomSignal<E>(map.keySet().toArray(new Class[]{}));
	}
	public CustomSlot createSlot(){
		CustomSlot slot =  new CustomSlot();
		for(Object obj:map.values()){
			for(Class itf : obj.getClass().getInterfaces()){
				for(Method method:itf.getMethods()){
					slot.put(method, obj);
				}
			}
		}
		return slot;
	}
	@SuppressWarnings("unchecked")
	public <E> Pair<E> createPair(){
		return new Pair(createSignal(),createSlot());
	}
	public static final class Pair<E>{
		public final CustomSignal<E> signal;
		public final CustomSlot slot;
		private Pair(CustomSignal<E> signal, CustomSlot slot) {
			synchronized(this){
				this.signal = signal;
				this.slot = slot;
				SlotBoard.connect(signal, slot);
			}
		}
	}
}
